package com.treasure.service.aop;

import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.treasure.service.commons.exception.BusinessException;
import com.treasure.service.constant.Constants;
import com.treasure.service.enums.HttpCode;
import com.treasure.service.result.ResponseResult;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @ClassName: ControllerAop
 * @author <a href="mailto:panxiwen@yingu.com">Pan Xinwen</a>
 * @date 2016年9月18日 下午4:29:34
 */
@Component
@Aspect
public class ControllerAop {

	private static Logger logger = LoggerFactory.getLogger(ControllerAop.class);

	@Pointcut("execution(* com.treasure.service.*.controller..*.*(..))")
	public void init() {

	}

	@Before(value = "init()")
	public void before(JoinPoint jp) {
		//Object[] args = jp.getArgs();
		//logger.info("---------方法执行前执行.....");
	}

	@AfterReturning(value = "init()")
	public void afterReturning() {
		//logger.info("---------方法执行完执行.....");
	}

	@AfterThrowing(value = "init()")
	public void throwss() {
		//logger.info("--------方法异常时执行.....");
	}

	@After(value = "init()")
	public void after() {
		//logger.info("-------方法最后执行.....");
	}

	/**
	 * 記錄日誌、全局異常處理
	 * @param pjp
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	@Around(value = "init()")
	public Object around(ProceedingJoinPoint pjp) throws Exception {
		boolean isLog = false;//是否記錄日誌
		boolean logException = false;//是否記錄異常日誌
//		OpSysLog sysLog = new OpSysLog();
//		LogInfo logInfo = null;
//		Gson g = new Gson();
		HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
	    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		Map<String, String[]> params=request.getParameterMap();
		Map<String, String[]> map=new HashMap<String, String[]>(params);
		String  uri=request.getRequestURI();
//		YinguSession session = OperatorContext.getSession();
//		 String username ="";
//        if(session!=null)  username = session.getUserName();
		map.put("uri", new String[]{uri});
		logger.info("访问uri：{}",uri);
		logger.info("参数列表：{}",JSON.toJSONString(map));
		String targetName = pjp.getTarget().getClass().getName();
        String methodName = pjp.getSignature().getName();

        logger.info("-------【方法 " + targetName + "." + methodName + "() 执行开始】.....");
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        for (int i = 0; i < methods.length; i++) {
			if(methodName.equals(methods[i].getName())){
//				logInfo = methods[i].getAnnotation(LogInfo.class);
//				if(null != logInfo){
					isLog = true;
//					logger.info("记录日志:" + logInfo.operationContent());
//					sysLog.setContent(logInfo.operationContent());
//					sysLog.setTypeKey(logInfo.logType().value());
//					sysLog.setTypeValue(logInfo.logType().name());
//					sysLog.setIp(getIpAddr(request));
//					sysLog.setParams(g.toJson(map));
//				}
			}
		}
		Object o = null;
		try {
			o = pjp.proceed();
			if(isLog){
				if(!logException){
//					logger.info("记录成功日志:" + logInfo.operationContent() + "-----成功！");
//					sysLog.setResult("1");
//					sysLog.setOperationTime(new Date());
//					sysLog.setOperator(username);
//					sysLog.setCoordinate("坐标【"+targetName + "." + methodName + "()】");
//					sysLogService.addSysLog(sysLog);
				}
			}
		} catch (Throwable e) {
			//异常信息处理
			StackTraceElement[]ste=e.getStackTrace();
			List<StackTraceElement> stackList=new ArrayList<StackTraceElement>();
			for(StackTraceElement elemmet:ste){
				if(StringUtils.contains(elemmet.getClassName(), "com.yingu")){
					stackList.add(elemmet);
				}
			}
			if(isLog){
				logException = true;
				logger.info("记录异常日志:" + e.toString()+":"+e.getLocalizedMessage());
//				if (e instanceof BusinessException) {
//					sysLog.setFailureCause(e.toString()+":"+e.getLocalizedMessage());
//				}else if(e instanceof IllegalArgumentException){
//					sysLog.setFailureCause(e.toString()+":"+e.getLocalizedMessage());
//				}else if(e instanceof Exception){
//					sysLog.setFailureCause(e.toString()+":"+e.getLocalizedMessage());
//				}else{
//					sysLog.setFailureCause(e.toString()+":"+e.getLocalizedMessage());
//				}
//				sysLog.setResult("0");
//				sysLog.setCoordinate(stackList.toString());
			}
			exceptionHandler(response,e);
		}
		if(isLog){
			if(logException){
//				sysLog.setOperationTime(new Date());
//				sysLog.setOperator(username);
//				sysLogService.addSysLog(sysLog);
			}
		}
		logger.info("-------【方法 " + targetName + "." + methodName + "() 执行结束】.....");
		return o;
	}

	/**
	 * 全局异常处理
	 * @param response
	 * @param e
	 * @throws Exception
	 */
	public void exceptionHandler(HttpServletResponse response, Throwable e) throws Exception {
		logger.error(Constants.Exception_Head, e);
		ResponseResult resultData = new ResponseResult();
		if (e instanceof IllegalArgumentException) {
			if (StringUtils.isNotBlank(e.getMessage())) {
				resultData.setCode(HttpCode.BAD_REQUEST.value());
				resultData.setMessage(e.getMessage());
			} else {
				resultData.setCode(HttpCode.BAD_REQUEST.value());
				resultData.setMessage(HttpCode.BAD_REQUEST.msg());
			}
		} else if (e instanceof BusinessException) {
			if (StringUtils.isNotBlank(e.getMessage())) {
				resultData.setCode(HttpCode.CONFLICT.value());
				resultData.setMessage(e.getMessage());
			} else {
				resultData.setCode(HttpCode.CONFLICT.value());
				resultData.setMessage(HttpCode.CONFLICT.msg());
			}
		} else {
			resultData.setCode(HttpCode.INTERNAL_SERVER_ERROR.value());
			resultData.setMessage(HttpCode.INTERNAL_SERVER_ERROR.msg());
		}
		response.setContentType("application/json;charset=UTF-8");
		Gson g = new Gson();
		byte[] bytes = g.toJson(resultData).getBytes();
		response.getOutputStream().write(bytes);
	}
	private  String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("X-Real-IP");
       if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
            return ip;
        }
       ip = request.getHeader("X-Forwarded-For");
       if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个IP值，第一个为真实IP。
           int index = ip.indexOf(',');
            if (index != -1) {
               return ip.substring(0, index);
            } else {
               return ip;
            }
        } else {
            return request.getRemoteAddr();
        }
    }
}
